package com.jarveis.frame.io;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.jarveis.frame.lang.CharacterUtil;

/**
 * IO工具类
 * 
 * @author liuguojun
 */
public class IOUtil {

	private static final Logger logger = Logger.getLogger(IOUtil.class);
	
	// 缓存区大小
	public static final int BUFFER_SIZE = 8 * 1024;

	/**
	 * 把输入流中的数据复制到输出流中
	 * 
	 * <pre>
	 * InputStream is = FileUtil.openInputStream("demo.txt");
	 * OutputStream os = FileUtil.openOutputStream("new.txt");
	 * IOUtil.write(is, os);
	 * ......
	 * IOUtil.close(os);
	 * IOUtil.close(is);
	 * </pre>
	 * 
	 * @param is
	 *            输入流
	 * @param os
	 *            输出流
	 * @throws IOException
	 */
	public static void write(InputStream is, OutputStream os) {
		if (is != null && os != null) {
			byte[] buffer = new byte[BUFFER_SIZE];
			int n = 0;
			try {
				while ((n = is.read(buffer)) != -1) {
					os.write(buffer, 0, n);
				}
				os.flush();
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}
		}
	}

	/**
	 * 把输入流中的数据复制到输出流中
	 * 
	 * <pre>
	 * OutputStream os = FileUtil.openOutputStream("new.txt");
	 * IOUtil.write("ssssss", os);
	 * ......
	 * IOUtil.close(os);
	 * </pre>
	 * 
	 * @param s
	 * @param os
	 */
	public static void write(String s, OutputStream os) {
		if (s != null && os != null) {
			try {
				os.write(s.getBytes(CharacterUtil.UTF8));
			} catch (IOException ex) {
				logger.error(ex.getMessage(), ex);
			}
		}
	}

	/**
	 * 把输入流中的数据复制到输出流中
	 * 
	 * <pre>
	 * OutputStream os = FileUtil.openOutputStream("new.txt");
	 * IOUtil.writeln("ssssss", os);
	 * ......
	 * IOUtil.close(os);
	 * </pre>
	 * 
	 * @param s
	 * @param os
	 */
	public static void writeln(String s, OutputStream os) {
		if (s != null && os != null) {
			write(s + "\n", os);
		}
	}

	/**
	 * 读取IO流中的字符串,并将每一行数据数组的元素中
	 * 
	 * <pre>
	 * demo.txt的内容如下：
	 * aaaaaaaaaaaaaaaaaaaaaaaaa
	 * bbbbbbbbbbbbbbbbbbbbbbbbb
	 * ccccccccccccccccccccccccc
	 * 
	 * [代码]
	 * InputStream is = Resource.getStream("demo.txt");
	 * String[] contents = IOUtil.reads(is);
	 * ......
	 * IOUtil.close(is);
	 * 
	 * [结果]
	 * contents = {
	 *     "aaaaaaaaaaaaaaaaaaaaaaaaa",
	 *     "bbbbbbbbbbbbbbbbbbbbbbbbb",
	 *     "ccccccccccccccccccccccccc"
	 * }
	 * </pre>
	 * 
	 * @param is
	 *            输入流
	 * @return String[]
	 * @throws IOException
	 */
	public static String[] reads(InputStream is) {
		return reads(is, CharacterUtil.UTF8);
	}

	/**
	 * 读取IO流中的字符串,并将每一行数据数组的元素中
	 * 
	 * <pre>
	 * demo.txt的内容如下：
	 * aaaaaaaaaaaaaaaaaaaaaaaaa
	 * bbbbbbbbbbbbbbbbbbbbbbbbb
	 * ccccccccccccccccccccccccc
	 * 
	 * [代码]
	 * InputStream is = Resource.getStream("demo.txt");
	 * String[] contents = IOUtil.reads(is, Constants.CHARSET_UTF8);
	 * ......
	 * IOUtil.close(is);
	 * 
	 * [结果]
	 * contents = {
	 *     "aaaaaaaaaaaaaaaaaaaaaaaaa",
	 *     "bbbbbbbbbbbbbbbbbbbbbbbbb",
	 *     "ccccccccccccccccccccccccc"
	 * }
	 * </pre>
	 * 
	 * @param is
	 *            输入流
	 * @return String[]
	 * @throws IOException
	 */
	public static String[] reads(InputStream is, String charset) {
		List<String> lines = new ArrayList<String>();

		if (is != null) {
			try {
				BufferedReader br = new BufferedReader(new InputStreamReader(
						is, charset == null ? CharacterUtil.UTF8 : charset));
				String line = null;
				while ((line = br.readLine()) != null) {
					lines.add(line);
				}
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}
		}

		return lines.toArray(new String[0]);
	}

	/**
	 * 读取IO流中的字符串,并将所有的行字符串合并成一个字符串
	 * 
	 * <pre>
	 * demo.txt的内容如下：
	 * aaaaaaaaaaaaaaaaaaaaaaaaa
	 * bbbbbbbbbbbbbbbbbbbbbbbbb
	 * ccccccccccccccccccccccccc
	 * 
	 * [代码]
	 * InputStream is = Resource.getStream("demo.txt");
	 * String content = IOUtil.read(is);
	 * ......
	 * IOUtil.close(is);
	 * 
	 * [结果]
	 * content = "aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc"
	 * </pre>
	 * 
	 * @param is
	 *            输入流
	 * @return String
	 * @throws IOException
	 */
	public static String read(InputStream is) {
		return read(is, CharacterUtil.UTF8);
	}

	/**
	 * 读取IO流中的字符串,并将所有的行字符串合并成一个字符串
	 * 
	 * <pre>
	 * demo.txt的内容如下：
	 * aaaaaaaaaaaaaaaaaaaaaaaaa
	 * bbbbbbbbbbbbbbbbbbbbbbbbb
	 * ccccccccccccccccccccccccc
	 * 
	 * [代码]
	 * InputStream is = Resource.getStream("demo.txt");
	 * String content = IOUtil.read(is, Constants.CHARSET_UTF8);
	 * ......
	 * IOUtil.close(is);
	 * 
	 * [结果]
	 * content = "aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc"
	 * </pre>
	 * 
	 * @param is
	 *            输入流
	 * @return String
	 * @throws IOException
	 */
	public static String read(InputStream is, String charset) {
		StringBuffer content = new StringBuffer();

		if (is != null) {
			try {
				BufferedReader br = new BufferedReader(new InputStreamReader(
						is, charset == null ? CharacterUtil.UTF8 : charset));
				String line = null;
				while ((line = br.readLine()) != null) {
					content.append(line).append('\n');
				}
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}
		}

		return content.toString();
	}

	/**
	 * 打开文件的输出流
	 * 
	 * @param filePath
	 * @return OutputStream
	 */
	public static OutputStream openOutputStream(String filePath) {
		return openOutputStream(new File(filePath));
	}

	/**
	 * 打开文件的输出流
	 * 
	 * @param file
	 * @return OutputStream
	 */
	public static OutputStream openOutputStream(File file) {
		FileOutputStream fos = null;

		if (file.exists()) {
			if (file.isDirectory()) {
				return null;
			}
			if (!(file.canWrite())) {
				return null;
			}
		} else {
			File parent = file.getParentFile();
			if ((parent != null) && (!parent.exists()) && (!parent.mkdirs())) {
				return null;
			}
		}
		try {
			fos = new FileOutputStream(file);
		} catch (FileNotFoundException ex) {
			logger.error(ex.getMessage(), ex);
		}

		return fos;
	}

	/**
	 * 打开文件的输入流
	 * 
	 * @param filePath
	 * @return InputStream
	 */
	public static InputStream openInputStream(String filePath) {
		return openInputStream(new File(filePath));
	}

	/**
	 * 打开文件的输入流
	 * 
	 * @param file
	 * @return InputStream
	 */
	public static InputStream openInputStream(File file) {
		FileInputStream fis = null;

		if (file.exists()) {
			if (file.isDirectory()) {
				return null;
			}
			if (!(file.canRead())) {
				return null;
			}
		} else {
			File parent = file.getParentFile();
			if ((parent != null) && (!parent.exists()) && (!parent.mkdirs())) {
				return null;
			}
		}
		try {
			fis = new FileInputStream(file);
		} catch (FileNotFoundException ex) {
			logger.error(ex.getMessage(), ex);
		}

		return fis;
	}

	/**
	 * 获取字符串的输入流
	 * 
	 * <pre>
	 * InputStream is = IOUtil.getInputStream("hello world!");
	 * ......
	 * </pre>
	 * 
	 * @param str
	 * @return InputStream
	 */
	public static InputStream getInputStream(String str) {
		return new ByteArrayInputStream(str.getBytes());
	}

	/**
	 * 获得读取字符流对象
	 * 
	 * <pre>
	 * Reader is = IOUtil.getReader("hello world!");
	 * ......
	 * </pre>
	 * 
	 * @param str
	 *            字符串
	 * @return 字符流的读取对象
	 */
	public static Reader getReader(String str) {
		return new StringReader(str);
	}

	/**
	 * 关闭输入流
	 * 
	 * <pre>
	 * InputStream is = IOUtil.getInputStream("hello world!");
	 * ......
	 * IOUtil.close(is);
	 * </pre>
	 * 
	 * @param is
	 *            输入流
	 */
	public static void close(InputStream is) {
		if (is != null) {
			try {
				is.close();
			} catch (IOException ex) {
				logger.error(ex.getMessage(), ex);
			}
		}
	}

	/**
	 * 关闭输出流
	 * 
	 * <pre>
	 * OutputStream os = FileUtil.openOutputStream("demo.txt");
	 * ......
	 * IOUtil.close(os);
	 * </pre>
	 * 
	 * @param os
	 *            输出流
	 */
	public static void close(OutputStream os) {
		if (os != null) {
			try {
				os.flush();
				os.close();
			} catch (IOException ex) {
				logger.error(ex.getMessage(), ex);
			}
		}
	}

	/**
	 * 关闭输入字符流
	 * 
	 * @param reader
	 */
	public static void close(Reader reader) {
		if (reader != null) {
			try {
				reader.close();
			} catch (IOException ex) {
				logger.error(ex.getMessage(), ex);
			}
		}
	}

	/**
	 * 关闭输出字符流
	 * 
	 * @param writer
	 */
	public static void close(Writer writer) {
		if (writer != null) {
			try {
				writer.flush();
				writer.close();
			} catch (IOException ex) {
				logger.error(ex.getMessage(), ex);
			}
		}
	}
}
